#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>

#include "bin_crc.h"
#include "bin2hex.h"
#include <time.h>


#define BOARD_MAGIC_NUMBER 0x407

#define INPUTFILE 	"input/ADAPTOR_RAW.bin"
#define OUTPUTFILE 	"output/adaptor_update.BIN"
#define OUTPUTFILE2 "output/bin_head_info.txt"

#define FULL_EDITTION 
#ifdef FULL_EDITTION
//完整HEX出厂文件
#define HEX_BOOTLOADER_INPUT_FILE 	"input/F4_BOOTLODAER.bin"
#define HEX_APP_INPUT_FILE 			OUTPUTFILE
#define HEX_OUTPUT_FILE 			"output/full_edition.hex"
#define HEX_BASE_BOOTLOADER_ADDR 0x08000000
#define HEX_BASE_APP_ADDR 		 0x08020000
#endif


static unsigned int calculateCRC32 (const unsigned char *pStart, unsigned int uSize);
static unsigned int ge_buildt_time(char *strbuf);
static void make_full_edition(void);

int main(int argc,char *argv[])
{

	unsigned int model 		= BOARD_MAGIC_NUMBER;
	unsigned int version=0, buildtime ;
	char strbuf[200]= {0};
	int fd,fdout,fdout2,len;
	unsigned int result_CRC;
	bin_head *pdata;
	unsigned char data[3*1024*1024] ={0};//2m
	pdata= (bin_head*)data;

	if(argc!=2){
		printf("###warning! need add a version argv such as this \"./bin_crc 1.10\" \n\n");
		return 0;
	}else{
		char *p= strstr(argv[1], "." );
		if(p!=NULL){
	  		version = (atoi(argv[1])<<0x8) | (atoi(p+1));
		}
	}
	ge_buildt_time(strbuf);
	buildtime= atoi(strbuf);
	pdata->model= model;
	pdata->buildtime= buildtime;
	pdata->version= version;
	printf("BIN file model: %x\n", model);
	printf("BIN file version: %d.%d\n", version>>0x8 ,version&0xff);
	printf("BIN file buildtime: %d\n", buildtime);
	fd 	= open(INPUTFILE, O_RDONLY,		 
			S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); 
	fdout = open(OUTPUTFILE, O_WRONLY | O_CREAT |O_TRUNC,		 
			S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); 
	fdout2= open(OUTPUTFILE2, O_WRONLY | O_CREAT |O_TRUNC,		 
			S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); 
	if(fd < 0 || fdout<0 ||  fdout2<0){
		printf("open file  failed, errno=%d.\n", errno);
		return -1;
	}
   	len= read(fd, &data[BIN_HEAD_LEN], 2*1024*1024-BIN_HEAD_LEN);
	unsigned char *dd = &data[BIN_HEAD_LEN];
	result_CRC=calculateCRC32(dd, len);
	pdata->crc32val= result_CRC;
	pdata->head_len= BIN_HEAD_LEN;
	pdata->data_len= len;
	if(-1 == write(fdout, pdata, len+BIN_HEAD_LEN))
		printf("erro, write failed\n");
	len= 0;
	len+= sprintf(strbuf+ len, "model:\t\t%08X\r\n", pdata->model);
	len+= sprintf(strbuf+ len, "version:\t%08X\r\n", pdata->version);
	len+= sprintf(strbuf+ len, "buildtime:\t%08X\r\n", pdata->buildtime);
	len+= sprintf(strbuf+ len, "crc32val:\t%08X\r\n", pdata->crc32val);
	len+= sprintf(strbuf+ len, "head_len:\t%08X\r\n", pdata->head_len);
	len+= sprintf(strbuf+ len, "data_len:\t%08X\r\n", pdata->data_len);
	len+= sprintf(strbuf+ len, "reserved1:\t%08X\r\n", pdata->reserved1);
	len+= sprintf(strbuf+ len, "reserved2:\t%08X\r\n", pdata->reserved2);
	printf("bin_head_info:\r\n%s", strbuf);
	if(-1 == write(fdout2, strbuf, len))
			printf("erro, write failed\n");
	fsync(fdout);	
	close(fd);	
	close(fdout);
	make_full_edition();
    return 0;
}


static void make_full_edition(void)
{
#ifdef FULL_EDITTION
	RESULT_STATUS res;
	unsigned char step=0; 
	res = BinFile2HexFile(HEX_BOOTLOADER_INPUT_FILE, HEX_OUTPUT_FILE, HEX_BASE_BOOTLOADER_ADDR, step++ );
	if(res!= RES_OK){
		printf("\r\nfull edition hex file: err, bootloader err!\r\n");
		return;
	}
	res = BinFile2HexFile(HEX_APP_INPUT_FILE, HEX_OUTPUT_FILE, HEX_BASE_APP_ADDR, step);
	if(res!= RES_OK)
		printf("\r\nfull edition hex file: app err!\r\n");
	else 
		printf("\r\nfull edition hex file: OK!\r\n");
#endif	
}


static unsigned int ge_buildt_time(char *strbuf)
{
    time_t timep;   
    struct tm *p; 
   
    time(&timep);   
    p = localtime(&timep);
   
    printf("ge_buildt_time: %02d%02d%02d\n", (p->tm_year-100), ( 1 + p->tm_mon),  p->tm_mday);
                         
	sprintf(strbuf,"%02d%02d%02d", (p->tm_year-100), ( 1 + p->tm_mon),  p->tm_mday);
    return 0;
}



static unsigned int calculateCRC32 (const unsigned char *pStart, unsigned int uSize)
{
	unsigned int uCRCValue;
	unsigned char *pData;
	uCRCValue = 0xFFFFFFFF;
	pData = (unsigned char*)pStart;
	while (uSize --)
	{
		uCRCValue = CRC32_Table[(uCRCValue ^ (*(pData++))) & 0xFF] ^ (uCRCValue >> 8);
	}
	return uCRCValue ^ 0xFFFFFFFF;
}



